home *** CD-ROM | disk | FTP | other *** search
/ IRIS Performer 2.2 Friends Demo / SGI IRIS Performer 2.2 Friends Demo.iso / friends / medit / pfLoader / Internalstuff / oldfiles.c < prev    next >
Text File  |  1997-11-20  |  17KB  |  732 lines

  1. /************************************************************************
  2. Stuff to help us convert older files into new files
  3. ************************************************************************/
  4. /* --- Sub object structure --- */
  5. #define SOS struct sub_object_struct
  6. typedef SOS {
  7. SOS        *Next;            /* Points to next sub object in object        */
  8. char        *Name;            /* Name of sub object                */
  9. int        Id;            /* Id (used during file operations        */
  10. PolygonPtr    FirstPolygon;        /* First polygon in this sub object        */
  11. int        Flag;            /* A useful flag                */
  12. } SubObject;
  13. typedef SubObject *SubObjectPtr;
  14. #undef SOS
  15.  
  16. SubObjectPtr SubObjectList = NULL;
  17.  
  18. /* these don't exist any more */
  19. enum { Unlit=0, Lit, Smooth };
  20. #define FPLighting FPSmooth
  21. #define FPTextureMat FPUnused
  22.  
  23. /************************************************************************
  24. Add a child to a tree branch (at the bottom of the list)
  25. ************************************************************************/
  26. static void AddChild(TreePtr parent, TreePtr newchild)
  27. {
  28.     reg TreePtr t = parent;
  29.     if (t->Across) {
  30.     t = t->Across;
  31.     while (t->Down) {
  32.         t = t->Down;
  33.     }
  34.     t->Down = newchild;
  35.     newchild->Down = NULL;
  36. #if ITSTHEMODELLER
  37.     newchild->Up = t;
  38.     newchild->Across = NULL;
  39.     newchild->Back = NULL;
  40. #endif
  41.     }
  42.     else {
  43.     t->Across = newchild;
  44.     newchild->Down = NULL;
  45. #if ITSTHEMODELLER
  46.     newchild->Up = NULL;
  47.     newchild->Across = NULL;
  48.     newchild->Back = t;
  49. #endif
  50.     }
  51. }
  52. /************************************************************************
  53. File revision 1.00 (ascii file, single object, no heirarchy)
  54. ************************************************************************/
  55. static float (*VertexList100)[XYZ];
  56.  
  57. #if !ITSTHEMODELLER
  58. #define MaxFileLine 1000
  59. static char FileData[MaxFileLine],*RestOfLine;
  60. static boolean ReadLineFromFile(FILE *f)
  61. {
  62.     reg char c,*s;
  63.     if (fgets(FileData,MaxFileLine,f) ISNT 0) {
  64.     c = *(s = FileData);            /* Remove trailing '\n' */
  65.     until ((c IS '\0') OR (c IS '\n')) {
  66.         c = *++s;
  67.     }
  68.     *s = '\0';
  69.     return TRUE;
  70.     }
  71.     else {
  72.     return FALSE;
  73.     }
  74. }
  75. #endif
  76.  
  77.  
  78. static boolean GetModelHeader100(FILE *f, char *Match, int *Count)
  79. {
  80.     float compatibility;
  81.     if ((sscanf(FileData,Match,&compatibility) ISNT 1) OR (compatibility ISNT 1.00)) {
  82.     SetError(BAD_FILE);
  83.     return FALSE;
  84.     }
  85.  
  86.     if (ReadLineFromFile(f)) {
  87.     if (sscanf(FileData,"Count: %d",Count) IS 1) {
  88.         return TRUE;
  89.     }
  90.     }
  91.     SetError(BAD_FILE);
  92.     return FALSE;
  93. }
  94. static boolean GetVertices100(FILE *f)
  95. {
  96.     int i,count;
  97.     float x,y,z;
  98.  
  99.     if (!GetModelHeader100(f,"Vertices (v%f)",&count)) {
  100.     return FALSE;
  101.     }
  102.  
  103.     VertexList100 = Allocate(count * sizeof(float) * XYZ);
  104.     for (i=0; i<count; i++) {
  105.     if (fscanf(f,"%f %f %f\n",&x,&y,&z) ISNT 3) {
  106.         SetError(BAD_FILE);
  107.         return FALSE;
  108.     }
  109.     VertexList100[i][X] =  x;
  110.     VertexList100[i][Y] = -z;
  111.     VertexList100[i][Z] =  y;
  112.     }
  113.     return TRUE;
  114. }
  115. static boolean GetPolygons100(FILE *f, TreePtr pnode)
  116. {
  117.     real c[XYZ];
  118.     PolygonPtr p;
  119.     PolygonBeadPtr pb;
  120.     int i, j, lighting;
  121.     int count, v, verts, mat;
  122.  
  123.     if (!GetModelHeader100(f,"Polygons (v%f)",&count)) {
  124.     return FALSE;
  125.     }
  126.     *CurrentMaterial() = NULL;
  127.     for (i=0; i<count; i++) {
  128.     if ((fscanf(f," Material:%d",        &mat) ISNT 1)
  129.     OR  (fscanf(f," Shading:%d",        &lighting) ISNT 1)
  130.     OR  (fscanf(f," Sides:%d - Vertices ",    &verts  ) ISNT 1) ) {
  131.         SetError(BAD_FILE);
  132.         return FALSE;
  133.     }
  134.     CurrentSmoothing = (lighting IS Smooth);
  135.     pb = NULL;
  136.     for (j=0; j<verts; j++) {
  137.         if (fscanf(f,"%d ",&v) ISNT 1) {
  138.         SetError(BAD_FILE);
  139.         return FALSE;
  140.         }
  141.         CopyXYZ(c, VertexList100[v]);
  142.         AddPolygonBead(&pb, c);
  143.     }
  144.     fscanf(f,"\n");
  145.     p = AddPolygon(pb,pnode,NULL);
  146.     p->Flag = mat;
  147.     }
  148.     return TRUE;
  149. }
  150.  
  151. #define M(x) m->x+0,m->x+1,m->x+2
  152. static boolean GetMaterials100(FILE *f, TreePtr t)
  153. {
  154.     flag used;
  155.     PolygonPtr p;
  156.     MaterialPtr m;
  157.     int i, no, count;
  158.     if (!GetModelHeader100(f,"Materials (v%f)",&count)) {
  159.     return FALSE;
  160.     }
  161.  
  162.     m = NULL;
  163.     for (i=0; i<count; i++) {
  164.     if (fscanf(f,"Material %d: ",&no) ISNT 1) {
  165.         return FALSE;
  166.     }
  167.     if (!m) {
  168.         m = NewMaterial();
  169.     }
  170.     ReadLineFromFile(f);
  171.     RenameMaterial(m, FileData);
  172.     if (fscanf(f,"RA:%f GA:%f BA:%f\n",M(Ambient))    ISNT 3) return FALSE;
  173.     if (fscanf(f,"RD:%f GD:%f BD:%f\n",M(Diffuse))    ISNT 3) return FALSE;
  174.     if (fscanf(f,"RS:%f GS:%f BS:%f\n",M(Specular)) ISNT 3) return FALSE;
  175.     if (fscanf(f,"Shine: %f\n",&(m->Shine))        ISNT 1) return FALSE;
  176.     used = FALSE;
  177.     LoopThroughBranchesPolygons(t, p) {
  178.         if (p->Flag IS i) {
  179.         used = TRUE;
  180.         p->Material = m;
  181.         }
  182.     }
  183.     if (used) {
  184.         AddMaterial(m);
  185.         m = NULL;
  186.     }
  187.     }
  188.     if (m) {
  189.     FreeMaterial(m);
  190.     }
  191.     *CurrentMaterial() = *FirstMaterial();
  192.     return TRUE;
  193. #undef M
  194. }
  195.  
  196. #define EX(x) (CurrentName + strlen(CurrentName) - strlen(x))
  197. void ReadModel100(FILE *f, char *fname)
  198. {
  199.     reg TreePtr pnode;
  200.     reg ModelObjectPtr o;
  201.     char name[MaxFileName], *n;
  202.     reg flag GotVertices, GotPolygons, GotMaterials;
  203.  
  204.     strcpy(name,fname);                    /* Generate name for object */
  205.     if (!strcmp(name + strlen(name) - strlen(FileExtension), FileExtension)) {
  206.     *(name + strlen(name) - strlen(FileExtension)) = '\0';
  207.     }
  208.     n = name;
  209.     while (strchr(n, '/')) {
  210.     n = strchr(n, '/') + 1;
  211.     }
  212.     o = AddObject(n);                    /* Basic object structure */
  213.     pnode = NewTreeBranch(PolygonBranch, n);
  214.     o->Tree = NewTreeBranch(GroupBranch, NULL);
  215.     AddChild(o->Tree, pnode);
  216.  
  217.     VertexList100 = NULL;                /* Read the file */
  218.     GotVertices = GotPolygons = GotMaterials = FALSE;
  219.     while (!FileError AND ReadLineFromFile(f)) {
  220.     if (!strncmp(FileData,"Ver",3)) {
  221.         GotVertices = GetVertices100(f);
  222.     }
  223.     else if (!strncmp(FileData,"Pol",3)) {
  224.         GotPolygons = GetPolygons100(f, pnode);
  225.     }
  226.     else if (!strncmp(FileData,"Mat",3)) {
  227.         GotMaterials = GetMaterials100(f, pnode);
  228.     }
  229.     }
  230.     if (FileError && (FileErrorType IS REACHED_END)) {
  231.     if (GotVertices && GotPolygons && GotMaterials) {
  232.         FileError = FALSE;
  233.         *CurrentMaterial() = NULL;
  234.     }
  235.     }
  236.     if (VertexList100) {
  237.     Free(VertexList100);
  238.     }
  239. }
  240.  
  241. /************************************************************************
  242. Read/write shorts...
  243. ************************************************************************/
  244. static boolean GetShort(reg FILE *f, reg int *Result)
  245. {
  246.     if (!FileError) {
  247.     int b1,b2;
  248.     if (!GetByte(f,&b1) OR !GetByte(f,&b2)) {
  249.         SetError(BAD_FILE);
  250.         return FALSE;
  251.     }
  252.     else {
  253.         *Result = (b1<<8) + b2;
  254.         return TRUE;    /* Ok */
  255.     }
  256.     }
  257.     else {
  258.     return FALSE;
  259.     }
  260. }
  261. /************************************************************************
  262. Pre 4.0 vertices...
  263. ************************************************************************/
  264. static int VListSize = 0;
  265. static real (*VListBase)[XYZ];
  266. static void ReadOldVertices(FILE *f)
  267. {
  268.     int i,count;
  269.     GetStuff(GetInt(f,&count));
  270.     if (count > VListSize) {
  271.     if (!VListSize) {
  272.         VListBase = malloc(count*XYZ*sizeof(real));
  273.     }
  274.     else {
  275.         VListBase = realloc(VListBase, count*XYZ*sizeof(real));
  276.     }
  277.     VListSize = count;
  278.     }
  279.     for (i=0; i<count; i++) {
  280.     GetStuff(GetReals(f,VListBase[i],XYZ));
  281.     TwistReal(VListBase[i]);
  282.     }
  283. }
  284. static void ReadOldVertex(FILE *f, PolygonPtr p)
  285. {
  286.     real c[XYZ];
  287.     int token, index;
  288.     flag HadCoord = FALSE;
  289.     PolygonBeadPtr lastpb = NULL;
  290.  
  291.     while (GetByte(f,&token)) {
  292.     switch (token) {
  293.         case BlockEnd:  return;
  294.  
  295.         case FVCoord:   if (HadCoord) {
  296.                 SetError(BAD_VERTEX);
  297.                 }
  298.                 else {
  299.                 HadCoord = TRUE;
  300.                 GetStuff(GetReals(f,c,XYZ));
  301.                 TwistReal(c);
  302.                 lastpb = AddPolygonBead(&(p->FirstBead),c);
  303.                 }
  304.                 break;
  305.  
  306.         case FVIndex:   if (HadCoord) {
  307.                 SetError(BAD_VERTEX);
  308.                 }
  309.                 else {
  310.                 HadCoord = TRUE;
  311.                 if (!VListBase) {
  312.                     SetError(BAD_VERTEX);
  313.                 }
  314.                 GetStuff(GetInt(f, &index));
  315.                 if ((index < 0) OR (index >= VListSize)) {
  316.                     SetError(BAD_VERTEX_INDEX);
  317.                 }
  318.                 else {
  319.                     lastpb = AddPolygonBead(&(p->FirstBead),VListBase[index]);
  320.                 }
  321.                 }
  322.                 break;
  323.  
  324.         case FVTexture: if (lastpb) {
  325.                 GetStuff(GetFloats(f,lastpb->TextureCoord,XY));
  326.                 }
  327.                 else {
  328.                 SetError(BAD_VERTEX);
  329.                 }
  330.                 break;
  331.  
  332.         case FVNormal:  if (lastpb) {
  333.                 GetStuff(GetFloats(f,lastpb->Normal,XYZ));
  334.                 TwistFloat(lastpb->Normal);
  335.                 }
  336.                 else {
  337.                 SetError(BAD_VERTEX);
  338.                 }
  339.                 FileHadNormals = TRUE;
  340.                 break;
  341.  
  342.         default:        if (!SkipFuture(f)) {
  343.                 SetError(BAD_VERTEX);
  344.                 }
  345.     }
  346.     }
  347. }
  348. /************************************************************************
  349. Pre 4.0 polygons
  350. ************************************************************************/
  351. static void ReadOldPolygon(reg FILE *f, PolygonPtr parent)
  352. {
  353.     int token, data;
  354.     reg MaterialPtr m;
  355.     reg PolygonPtr p = NewPolygon();
  356.  
  357.     if (parent) {
  358.     p->Next = parent->Child;
  359.     parent->Child = p;
  360.     }
  361.     else {
  362.     p->Next = SubObjectList->FirstPolygon;
  363.     SubObjectList->FirstPolygon = p;
  364.     }
  365.  
  366.     while (GetByte(f,&token)) {
  367.     switch (token) {
  368.         case BlockEnd:    if (p->Coloured) {
  369.                     m = p->Material;
  370.                     p->Colour  = ((lcolour)(m->Diffuse[0]*255)) << 16;
  371.                     p->Colour |= ((lcolour)(m->Diffuse[1]*255)) << 8;
  372.                     p->Colour |= ((lcolour)(m->Diffuse[2]*255));
  373.                     p->Colour |= ((lcolour)(m->Alpha     *255)) << 24;
  374.                     p->Material = NULL;
  375.                 }
  376.                 return;
  377.  
  378.         case FPolygon:    ReadOldPolygon(f,p);
  379.                 break;
  380.  
  381.         case FPMaterial:    if (Compatibility < 3.00) {
  382.                     GetStuff(GetByte(f,&data));
  383.                 }
  384.                 else {
  385.                     GetStuff(GetShort(f,&data));
  386.                 }
  387.                 p->Material = MaterialList[data];
  388.                 break;
  389.  
  390.         case FPLighting:    GetStuff(GetByte(f,&data));
  391.                 switch (data) {
  392.                     case Unlit:    p->Coloured = TRUE;
  393.                         p->Smooth = FALSE;
  394.                         break;
  395.                     case Lit:    p->Coloured = FALSE;
  396.                         p->Smooth = FALSE;
  397.                         break;
  398.                     case Smooth:p->Coloured = FALSE;
  399.                         p->Smooth = TRUE;
  400.                         break;
  401.                 }
  402.                 break;
  403.  
  404.         case FPNormal:    GetStuff(GetFloats(f,p->Normal,XYZ));
  405.                 TwistFloat(p->Normal);
  406.                 FileHadNormals = TRUE;
  407.                 break;
  408.  
  409.         case FPTexture:    GetStuff(GetInt(f,&data));
  410.                 p->Texture = TextureList[data];
  411.                 break;
  412.  
  413.         case FPTextureMat:    if (Compatibility < 3.00) {
  414.                     GetStuff(GetByte(f,&data));
  415.                 }
  416.                 else {
  417.                     GetStuff(GetShort(f,&data));
  418.                 }
  419.                 p->Material = MaterialList[data];
  420.                 break;
  421.  
  422.         case FPLightGroup:    GetStuff(GetInt(f,&(p->LightGroup)));
  423.                 break;
  424.  
  425.         case FPEnvmapped:    GetStuff(GetByte(f,&data));
  426.                 p->Envmapped = (data&1) ISNT 0;
  427.                 break;
  428.  
  429.         case FVertex:    ReadOldVertex(f, p);
  430.                 break;
  431.  
  432.         default:        if (!SkipFuture(f)) {
  433.                     SetError(BAD_POLYGON);
  434.                 }
  435.     }
  436.     }
  437. }
  438. /************************************************************************
  439. SubObjects...
  440. ************************************************************************/
  441. static SubObjectPtr FindSubObject(int id, char *name)
  442. {
  443.     reg SubObjectPtr s = SubObjectList;
  444.     while (s) {
  445.     if (name) {
  446.         if (!strcmp(name, s->Name)) {
  447.         return s;
  448.         }
  449.     }
  450.     else if (s->Id IS id) {
  451.         return s;
  452.     }
  453.     s = s->Next;
  454.     }
  455.     SetError(BAD_SUB_OBJECT);
  456.     return NULL;
  457. }
  458. static void TrashChildren(reg PolygonPtr p)
  459. {
  460.     reg PolygonPtr next;
  461.     while (p) {
  462.     next = p->Next;
  463.     if (p->Child) {
  464.         TrashChildren(p->Child);
  465.     }
  466.     TrashPolygon(p);
  467.     p = next;
  468.     }
  469. }
  470. static void FreeSubObjects(void)
  471. {
  472.     reg PolygonPtr p, nextp;
  473.     reg SubObjectPtr next, s = SubObjectList;
  474.     while (s) {
  475.     next = s->Next;
  476.     p = s->FirstPolygon;
  477.     while (p) {
  478.         nextp = p->Next;
  479.         if (p->Child) {
  480.         TrashChildren(p->Child);
  481.         }
  482.         TrashPolygon(p);
  483.         p = nextp;
  484.     }
  485.     Free(s->Name);
  486.     Free(s);
  487.     s = next;
  488.     }
  489.     SubObjectList = NULL;
  490. }
  491. static void ReadSubObject(FILE *f)
  492. {
  493.     int token;
  494.     SubObjectPtr new;
  495.     char name[MaxName];
  496.  
  497.     new = Allocate(sizeof(SubObject));
  498.     new->Next = SubObjectList;
  499.     SubObjectList = new;
  500.  
  501.     GetString(f,name,MaxName);
  502.     new->Name = CopyOfString(name);
  503.     new->FirstPolygon = NULL;
  504.  
  505.     while (GetByte(f,&token)) {
  506.     switch (token) {
  507.         case BlockEnd:    return;
  508.  
  509.         case FSubObjectId:    GetInt(f,&(SubObjectList)->Id);
  510.                 break;
  511.  
  512.         case FVList:    ReadOldVertices(f);
  513.                 break;
  514.  
  515.         case FPolygon:    ReadOldPolygon(f,NULL);
  516.                 break;
  517.  
  518.         default:        if (!SkipFuture(f)) {
  519.                     SetError(BAD_SUB_OBJECT);
  520.                 }
  521.     }
  522.     }
  523. }
  524. static void GetPolysFromSubObject(TreePtr lod, SubObjectPtr s)
  525. {
  526.     char *n;
  527.     TreePtr t;
  528.     PolygonPtr new, p;
  529.  
  530.     p = s->FirstPolygon;
  531.     n = strstr(s->Name, "SubObject")? NULL: s->Name;
  532.     t = NewTreeBranch(PolygonBranch, n);
  533.     while (p) {
  534.     new = CopyOfPolygon(p);
  535.     LinkPolygon(new, t, NULL);
  536.     p = p->Next;
  537.     }
  538.     AddChild(lod, t);
  539. }
  540. static void ReadLod(FILE *f, ModelObjectPtr o)
  541. {
  542.     TreePtr lod;
  543.     SubObjectPtr s;
  544.     float switchout;
  545.     char name[MaxName];
  546.     int token, id, value;
  547.  
  548.     GetString(f,name,MaxName);
  549.     lod = NewTreeBranch(LodBranch, name);
  550.     if (!o->Tree) {
  551.     o->Tree = NewTreeBranch(GroupBranch, NULL);
  552.     }
  553.     AddChild(o->Tree, lod);
  554.  
  555.     while (GetByte(f,&token)) {
  556.     switch (token) {
  557.         case BlockEnd:    return;
  558.  
  559.         case FSwitchOut:    GetFloats(f,&switchout,1);
  560.                 lod->SwitchOut = fabs(switchout);
  561.                 break;
  562.  
  563.         case FSubObject:    GetString(f,name,MaxName);
  564.                 if (s = FindSubObject(-1, name)) {
  565.                     GetPolysFromSubObject(lod, s);
  566.                 }
  567.                 else {
  568.                     SetError(SUB_OBJECT_NOT_FOUND);
  569.                 }
  570.                 break;
  571.  
  572.         case FBeadVisible:    GetStuff(GetInt(f, &value));
  573. #if ITSTHEMODELLER
  574.                 lod->EyeOpen = value;
  575. #endif
  576.                 break;
  577.  
  578.         case FSubObjectId:    GetStuff(GetInt(f,&id));
  579.                 if (s = FindSubObject(id, NULL)) {
  580.                     GetPolysFromSubObject(lod, s);
  581.                 }
  582.                 else {
  583.                     SetError(SUB_OBJECT_NOT_FOUND);
  584.                 }
  585.                 break;
  586.     
  587.         default:        if (!SkipFuture(f)) {
  588.                     SetError(BAD_LOD);
  589.                 }
  590.     }
  591.     }
  592. }
  593. /************************************************************************
  594. Read the scene tree...
  595. ************************************************************************/
  596. static void ReadScene(FILE *f, TreePtr parent)
  597. {
  598.     TreePtr new;
  599.     int token, n;
  600.     char name[MaxFileName];
  601.  
  602.     GetString(f,name,MaxFileName);
  603.     new = NewTreeBranch(GroupBranch, name);
  604.     AddChild(parent, new);
  605.  
  606.     while (GetByte(f,&token)) {
  607.     switch (token) {
  608.         case FPop:        return;
  609.     
  610.         case FPush:        ReadScene(f,new);
  611.                 break;
  612.     
  613.         case FBranch:    if (GetString(f,name,MaxFileName)) {
  614.                     new = NewTreeBranch(GroupBranch, name);
  615.                     AddChild(parent, new);
  616.                 }
  617.                 else {
  618.                     SetError(BAD_TREE);
  619.                 }
  620.                 break;
  621.     
  622.         case FInstance:    new->Type = InstanceBranch;
  623.                 GetStuff(GetInt(f, &(new->ObjId)));
  624.                 break;
  625.     
  626.         case FMatrix:    GetStuff(GetMatrix(f,new->Transformation));
  627.                 break;
  628.     
  629.         case FVisible:    GetStuff(GetInt(f, &n));
  630. #if ITSTHEMODELLER
  631.                 new->EyeOpen = n;
  632. #endif
  633.                 break;
  634.  
  635.         case FFolded:    GetStuff(GetInt(f, &n));
  636. #if ITSTHEMODELLER
  637.                 new->Folded = n;
  638. #endif
  639.                 break;
  640.  
  641.         default:        if (!SkipFuture(f)) {
  642.                     SetError(BAD_TREE);
  643.                 }
  644.     }
  645.     }
  646. }
  647. static ModelObjectPtr OldScene;
  648. static void ReadOldScene(FILE *f)
  649. {
  650.     OldScene = AddObject("Scene");
  651.     OldScene->Id = -1;        /* This id can't exist normally... */
  652.     OldScene->IsTopLevel = TRUE;
  653.     OldScene->Tree = NewTreeBranch(GroupBranch, "Scene");
  654.     ReadScene(f, OldScene->Tree);
  655. }
  656. #if ITSTHEMODELLER
  657. static void DealWithSceneView(reg int id, reg ViewPtr view)
  658. {
  659.     if (OldScene) {
  660.     *CurrentObject() = OldScene;
  661.     if ((id >= 0x200) AND (id < (0x200+NoViews))) {
  662.         CopyView(DefaultObject2D(id-0x200),view);
  663.     }
  664.     else if (id IS 0x23d) {
  665.         CopyView(DefaultObject3D(),view);
  666.     }
  667.     else if ((id >= 0x300) AND (id < (0x300+MaxViewports))) {
  668.         CopyView(ObjectView(id-0x300),view);
  669.     }
  670.     }
  671. }
  672. static void RememberSceneGridIndex(int n)
  673. {
  674.     if (OldScene) {
  675.     *CurrentObject() = OldScene;
  676.     *GridIndex() = n;
  677.     }
  678. }
  679. static void RememberSceneGridSteps(int n)
  680. {
  681.     if (OldScene) {
  682.     *CurrentObject() = OldScene;
  683.     *GridSteps() = n;
  684.     }
  685. }
  686. #endif
  687. /************************************************************************
  688. Set billboard attribute
  689. ************************************************************************/
  690. static void SetBillboarding(reg TreePtr t)
  691. {
  692.     while (t) {
  693.     if (t->Type IS PolygonBranch) {
  694.         t->Billboard = TRUE;
  695.     }
  696.     if (t->Across) {
  697.         SetBillboarding(t->Across);
  698.     }
  699.     t = t->Down;
  700.     }
  701. }
  702. /************************************************************************
  703. Remove pointless LODs from old files
  704. ************************************************************************/
  705. void RemoveEmptyLods(ModelObjectPtr o)
  706. {
  707.     reg TreePtr l;
  708.     if (o->Tree) {
  709.     l = o->Tree->Across;
  710.     if ((l->Type IS LodBranch) AND l->Across AND !l->Down) {
  711.         if (l->SwitchOut > 999999) {    /* Default switch distance */
  712. #if ITSTHEMODELLER
  713.         l->Back->Across = l->Across;
  714.         l->Across->Back = l->Back;
  715. #else
  716.         o->Tree->Across = l->Across;
  717. #endif
  718.         l->Across = NULL;
  719.         FreeTree(l);
  720.         }
  721.     }
  722.     }
  723. }
  724. /************************************************************************
  725. Read original texture directory...
  726. ************************************************************************/
  727. static void ReadTextureDir(FILE *f)
  728. {
  729.     char junk[MaxFileName];
  730.     GetString(f,junk,MaxFileName);
  731. }
  732.